package model

import (
	"context"
	"fmt"
	"log"
	"os"
	"project-info/src/lib"
	"time"
	m "gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
)

var db *gorm.DB

func DbInit() {
	loggerConfig := logger.Config{
		SlowThreshold:             time.Second, // 慢 SQL 阈值
		LogLevel:                  logger.Info, // 日志级别, 改为logger.Info即可显示sql语句
		IgnoreRecordNotFoundError: true,        // 忽略ErrRecordNotFound（记录未找到）错误
		Colorful:                  false,       // 禁用彩色打印
	}
	log := logger.New(log.New(os.Stdout, "\r\n", log.LstdFlags), loggerConfig)
	gormConfig := &gorm.Config{
		Logger: log,
	}
	newDb, err := gorm.Open(m.Open(fmt.Sprintf("%s:%s@(%s:%s)/%s?charset=utf8mb4&parseTime=True&loc=Local", C.Mysql.User, C.Mysql.Password, C.Mysql.Host, C.Mysql.Port, C.Mysql.Db)), gormConfig)
	if err != nil {
		newDb, err = gorm.Open(m.Open(fmt.Sprintf("%s:%s@(%s)/%s?charset=utf8mb4&parseTime=True&loc=Local", os.Getenv("MYSQL_USER"), os.Getenv("MYSQL_PASSWORD"), os.Getenv("MYSQL_ADDR"), os.Getenv("MYSQL_DB"))), gormConfig)
		if err != nil {
			log.Error(context.Background(), "mysql连接失败! 亲 数据库建了没？ 配置填对了没？")
			os.Exit(1)
		}
	}

	db = newDb
	sqlDb, err := db.DB()
	if err != nil {
		fmt.Println("获取数据库连接失败!")
		os.Exit(1)
	}

	// 注册全局插件
	registerCreateCallback()
	registerUpdateCallback()

	//db.LogMode(C.Mysql.PrintSql)
	//sqlDb := db.DB()
	sqlDb.SetConnMaxLifetime(time.Minute * 10)
	sqlDb.SetMaxOpenConns(50)
	sqlDb.SetMaxIdleConns(15)
}

func DB() *gorm.DB {
	return db
}

func DBWithGinContext(c *lib.GinContext) *gorm.DB {
	token := lib.JwtParse(c)
	return DBWithCtx(context.WithValue(context.Background(), "token", token))
}

func DBWithToken(token *lib.Token) *gorm.DB {
	return DBWithCtx(context.WithValue(context.Background(), "token", token))
}

func DBWithCtx(context context.Context) *gorm.DB {
	return DB().WithContext(context)
}

func registerCreateCallback() {
	db.Callback().Create().Before("gorm:create").Register("auto_fill_creator", func(db *gorm.DB) {
		if user, ok := db.Statement.Context.Value("token").(*lib.Token); ok {
			db.Statement.SetColumn("creator_id", user.UserId)
			db.Statement.SetColumn("creator", user.UserName)
		}
	})
}

func registerUpdateCallback() {
	db.Callback().Update().Before("gorm:update").Register("auto_fill_updater", func(db *gorm.DB) {
		db.Omit("creator_id", "creator", "create_time")
		if user, ok := db.Statement.Context.Value("token").(*lib.Token); ok {
			db.Statement.SetColumn("modifier_id", user.UserId)
			db.Statement.SetColumn("modifier", user.UserName)
		}
	})
}
